package com.dgsrz.demo.util;

import android.app.Activity;
import android.graphics.PointF;
import android.util.DisplayMetrics;
import android.view.Window;

import javax.microedition.khronos.opengles.GL;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11ExtensionPack;

/**
 * @author dgsrz
 * @author fuuko
 */
public class GameUtils {

    public static final String GL_EXT_FBO = "GL_OES_framebuffer_object";

    public static int createTargetTexture(GL10 gl, int width, int height) {
        int[] textures = new int[1];
        gl.glGenTextures(1, textures, 0);

        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
        gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, width, height, 0,
                        GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, null);

        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
        gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
        gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
        return textures[0];
    }

    public static int createFrameBuffer(GL10 gl, int width, int height, int textureId) {
        GL11ExtensionPack gl11ep = (GL11ExtensionPack) gl;

        int frameBufferId;
        int[] frameBuffers = new int[1];
        gl11ep.glGenFramebuffersOES(1, frameBuffers, 0);
        frameBufferId = frameBuffers[0];
        gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, frameBufferId);

        int depthBuffer;
        int[] renderBuffers = new int[1];
        gl11ep.glGenRenderbuffersOES(1, renderBuffers, 0);
        depthBuffer = renderBuffers[0];

        gl11ep.glBindRenderbufferOES(GL11ExtensionPack.GL_RENDERBUFFER_OES, depthBuffer);
        gl11ep.glRenderbufferStorageOES(GL11ExtensionPack.GL_RENDERBUFFER_OES,
                                        GL11ExtensionPack.GL_DEPTH_COMPONENT16, width, height);
        gl11ep.glFramebufferRenderbufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES,
                                            GL11ExtensionPack.GL_DEPTH_ATTACHMENT_OES,
                                            GL11ExtensionPack.GL_RENDERBUFFER_OES, depthBuffer);
        gl11ep.glFramebufferTexture2DOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES,
                                         GL11ExtensionPack.GL_COLOR_ATTACHMENT0_OES, GL10.GL_TEXTURE_2D,
                                         textureId, 0);

        int status = gl11ep.glCheckFramebufferStatusOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES);
        if (status != GL11ExtensionPack.GL_FRAMEBUFFER_COMPLETE_OES) {
            throw new RuntimeException("Framebuffer is not complete: " +
                                       Integer.toHexString(status));
        }

        gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, 0);
        return frameBufferId;
    }

    public static boolean checkExtensionCompatibility(GL10 gl, String extension) {
        String extensions = " " + gl.glGetString(GL10.GL_EXTENSIONS) + " ";
        return extensions.contains(" " + extension + " ");
    }

    public static void checkGLErrors(GL gl) {
        int error = ((GL10) gl).glGetError();
        if (error != GL10.GL_NO_ERROR) {
            throw new RuntimeException("GLError 0x" + Integer.toHexString(error));
        }
    }

    public static PointF getRealPos(Activity context, PointF inPos) {
        final DisplayMetrics dm = new DisplayMetrics();
        context.getWindowManager().getDefaultDisplay().getMetrics(dm);
        int contentTop = context.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();

        // Scale to fit 4:3
        float width = dm.widthPixels - contentTop;
        float height = dm.heightPixels;
        if (width * 3 > height * 4) {
            width = height * 4 / 3;
        } else {
            height = width * 3 / 4;
        }

        float multiplier = height / Constants.BOUNDARY_Y * 0.85f;
        float posX = dm.widthPixels / 2.0f - Constants.BOUNDARY_X * multiplier / 2.0f;
        float posY = (dm.heightPixels - contentTop) / 2.0f - Constants.BOUNDARY_Y * multiplier / 2.0f;

        PointF outPos = new PointF();
        outPos.x = inPos.x * multiplier;
        outPos.x += posX;
        outPos.y = inPos.y * multiplier;
        outPos.y += posY;
        return outPos;
    }
}
